/* ========================================================================== */
/*                                                                            */
/*   Toggle.c                                                                 */
/*   (c) 2008 Ruud Nabben <r.nabben@gmail.com>                                */
/*                                                                            */
/*   Simple program to test IO ports and interrupt mechanism                  */
/*                                                                            */
/* ========================================================================== */

/* 
 * Compile with:
 *    zcc +embedded ns16450.o toggle.c -otoggle.bin -lim2 -lembedded_clib2
 *    
 * Convert to VHDL with:
 *   hex2rom.exe -b toggle.bin toggle 16l8z > toggle.vhd
 *  Make sure ram size and address are defined correctly in embedded_crt0.asm
 *  
 * Use makelib.bat to compile embedded_clib2 and ns16450.o
 * 
 *zcc +embedded ns16450.o toggle.c -o toggle.bin -lim2  -I. -lembedded_clib2     
 */  
 
 
 //usage:
 //1:  zcc +embedded ns16450.o toggle.c -o toggle.bin -lim2  -I. -lembedded_clib2
 //2:  hex2rom.exe -b toggle.bin toggle 16l8a > toggle.vhd
 

#include <stdio.h>
#include <stdlib.h>
#include <im2.h>
#include "ns16450.h"
#include "keymap.h"

#define INT_DISABLE()   asm("di")
#define INT_ENABLE()    asm("ei")

#define IOPORT1_BASE		0x0010
#define IOPORT0_BASE		0x0020
#define KEYBOARD_BASE		0x0030

static char *int_mask = 0x4000;
static char *key_int = 0x80f0;
static char *count = 0x80f4;
static char cnt;

static void set_interrupt_mask(char mask)
{
  INT_DISABLE();
  *int_mask = mask;
  INT_ENABLE();  
}

static void enable_int(char mask)
{
  INT_DISABLE();
  *int_mask = *int_mask | mask;
  INT_ENABLE();      
}

static void disable_int(char mask)
{
  INT_DISABLE();
  *int_mask = *int_mask & ~mask;  
  INT_ENABLE();
}

static void enable_int_dis(char mask)
{
  *int_mask = *int_mask | mask;  
}

static void disable_int_dis(char mask)
{
  *int_mask = *int_mask & ~mask;  
}

void key_pressed(void)
{
  disable_int_dis(0x01);
  cnt += 1;    
  *count += 1;
  printf("In ISR, count: %u\n\r", cnt);
  outp(0x10, cnt);
  *key_int = 1;
}

void sleep2(void)
{
	int i;
	for(i = 0; i < 1000; i++)
	{
	}
}

M_BEGIN_ISR(toggle_isr)
/* interrupts are disabled during this function */
  printf("Active: %u\n\r", *int_mask);    
  key_pressed();
M_END_ISR

void main()
{
  cnt = 0;  
  INT_DISABLE();
      
/*  *int_mask = 0x00;
  *key_int = 0;  
  *count = 0;    
*/
  //outp(0x10, 0x81);
  //outp(0x20, 0x81);

  /* convert 24 MHz to 16*baudrate
         9600 : 0x9c
       115200 : 0x0d
  */
  init_uart(0x00, 0x0d); 
  //im2_Init(1, 0x8000,  toggle_isr);

/* enable interrupts*/
  //INT_ENABLE();
  //outp(0x10, 0x42);
  //outp(0x20, 0x42);
  printf("Hello world!\n\r");
  //enable_int(0x01);
  //outp(0x10, 0x24);
  //outp(0x20, 0x24);
  
 
  for (;;)
  {
    int scan_code = 0;
    char lsr = 0;
    int ps2_fifo_empty = 0;
    int ps2_fifo_status = 0;
    
    //if (*key_int == 1)
    //{
    //  printf("In main, count: %u\n\r", *count);
    //  outp(0x20, *count);
    //  *key_int = 0;
    //  enable_int(0x01);      
    //}
    
    lsr = inp(UART_BASE + LSR);
    if (lsr & 0x01)
    {
      char ch;
      ch = inp(UART_BASE + RBR);
      /* assume uart can send faster than we can fill buffer,
      so no checking of lsr */
      outp(UART_BASE + THR, ch + 1);
    }
    
    ps2_fifo_status = inp(IOPORT1_BASE);
    ps2_fifo_empty = ps2_fifo_status & 0x1;
    
    printf("ps2_fifo_status: %x\r\n", ps2_fifo_status);
    
    while(ps2_fifo_empty == 0)
    {
    	//get key scan code
    	outp(IOPORT1_BASE, 0x1);
    	scan_code = inp(KEYBOARD_BASE);
    	outp(IOPORT1_BASE, 0x0);

	    ps2_fifo_status = inp(IOPORT1_BASE);
	    ps2_fifo_empty = ps2_fifo_status & 0x1;
	    
	    printf("ps2_fifo_status: %x\r\n", ps2_fifo_status);
			printf("scan code: %x\r\n", scan_code);

			//write key scan code
   		if (scan_code != 0xF0)
   		{
   			outp(UART_BASE + THR, keymap[scan_code]);
   		}

    }

    	
  }
}


